package com.mobile.framework.util;

import java.beans.PropertyDescriptor;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.upload.FormFile;

/**
 * Common utilities.
 */
public class Util {

	private static Log log = LogFactory.getLog(Util.class);

	static SimpleDateFormat df = new SimpleDateFormat(Constants.DATE_FORMAT);

	/**
	 * Encrypt the string with MD5 algorithm
	 * 
	 * @param str
	 *            input clear text string
	 * @return Return encrypted string.
	 */
	public static String encrypt(String str) {
		String encryptStr = null;
		if (str == null) {
			return null;
		}
		try {
			/*
			 * 
			 * //��Ϊʹ��JDK�Դ��MD5�㷨�������ַ��Ա�ȥ���cryptix������ MessageDigest alga =
			 * MessageDigest.getInstance("MD5", "Cryptix"); byte[] digest =
			 * alga.digest(str.getBytes()); encryptStr = Hex.toString(digest);
			 */
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(str.getBytes());
			BigInteger hash = new BigInteger(1, md.digest());
			encryptStr = hash.toString(16);
			//encryptStr = hash.toString(16).toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return encryptStr;
	}

	/**
	 * Filter the specified string for characters that are senstive to HTML
	 * interpreters, returning the string with these characters replaced by the
	 * corresponding character entities. from struts 1.1
	 * org.apache.struts.taglib.TagUtils
	 * 
	 * @param value
	 *            The string to be filtered and returned
	 */
	public static String filterHtml(String value) {

		if (value == null) {
			return (null);
		}

		char content[] = new char[value.length()];
		value.getChars(0, value.length(), content, 0);
		StringBuffer result = new StringBuffer(content.length + 50);

		for (int i = 0; i < content.length; i++) {
			switch (content[i]) {
			case '<':
				result.append("&lt;");
				break;
			case '>':
				result.append("&gt;");
				break;
			case '&':
				result.append("&amp;");
				break;
			case '"':
				result.append("&quot;");
				break;
			case '\'':
				result.append("&#39;");
				break;
			default:
				result.append(content[i]);
			}
		}

		return result.toString();
	}

	/**
	 * Retrieve current time stamp value.
	 * 
	 * @return a Timestamp object.
	 */
	public static Timestamp getCurrentTime() {
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * split string
	 * 
	 * @param src
	 * @param prefix
	 */
	public static String[] splitString(String src, String prefix) {
		int pos = 0;
		int size = 10;
		int i = 0;
		int p = 0;
		String[] fix = new String[10];
		while (true) {
			p = src.indexOf(prefix, i);
			if (p == -1) {
				break;
			}
			if (pos == size) {
				size += 10;
				String[] tmp = new String[size];
				System.arraycopy(fix, 0, tmp, 0, pos);
				fix = tmp;
			}
			fix[pos] = src.substring(i, p);
			pos++;
			i = p + prefix.length();
		}
		String tmp[] = new String[pos + 1];
		tmp[pos] = src.substring(i);
		System.arraycopy(fix, 0, tmp, 0, pos);
		return tmp;
	}

	/**
	 * ʹ��ȱʡ��ʽת���ִ�Ϊ����
	 * 
	 * @param date
	 *            �����ִ�
	 * @return Date
	 */
	public static Date parseDate(String date) {
		return parseDate(date, Constants.DATE_FORMAT);
	}

	/**
	 * ����ʽת���ִ�Ϊ����
	 * 
	 * @param date
	 *            �����ִ�
	 * @param format
	 *            ��ʽ
	 * @return Date
	 */
	public static Date parseDate(String date, String format) {
		if (date == null || date.equals("")) {
			return null;
		}
		SimpleDateFormat f = new SimpleDateFormat(format);
		Date d = null;
		try {
			d = f.parse(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return d;
	}

	/**
	 * ʹ��ȱʡ��ʽת������Ϊ�ִ�
	 * 
	 * @param date
	 *            �����ִ�
	 * @return String
	 */
	public static String formatDate(Date date) {
		return formatDate(date, Constants.DATE_FORMAT);
	}

	/**
	 * ����ʽת������Ϊ�ִ�
	 * 
	 * @param date
	 *            �����ִ�
	 * @param format
	 *            ��ʽ
	 * @return String
	 */
	public static String formatDate(Date date, String format) {
		if (date == null) {
			return "";
		}
		SimpleDateFormat f = new SimpleDateFormat(format);
		return f.format(date);
	}

	/**
	 * amount Days on the Date.
	 * 
	 * @param date
	 * @param amount
	 * @return date
	 */
	public static Date amountDay(Date date, int amount) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DATE, amount);
		return c.getTime();
	}

	/**
	 * ����Date��ʱ���ֶΣ�ʱ���֡��롢���룩ȫ����0
	 * 
	 * @param d
	 * @return a Date
	 */
	public static Date cleanTimeFields(Date d) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(d);
		// clean the time fields

		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	/**
	 * Convert a null string to an empty string.
	 * 
	 * @param s
	 * @return �ǿ��ַ�
	 */
	public static String nullToString(String s) {
		return (s == null) ? "" : s;
	}

	/**
	 * ȡ�÷ǿ��ַ�
	 * 
	 * @param o
	 *            Դ��
	 * @param defaultStr
	 *            ȱʡ��
	 * @return �������ִ�
	 */
	public static String getString(Object o, String defaultStr) {
		if (null == o) {
			return defaultStr;
		}
		String ret = (String) o;
		return ("".equals(ret)) ? defaultStr : ret;
	}

	/**
	 * �滻�ַ�����Ӵ�
	 * 
	 * @param str
	 *            Դ�ִ�
	 * @param pattern
	 *            ���滻�Ĵ�
	 * @param replace
	 *            �滻�ɵĴ�
	 * @return String
	 */
	public static String replace(String str, String pattern, String replace) {
		int s = 0;
		int e = 0;
		StringBuffer result = new StringBuffer();
		while ((e = str.indexOf(pattern, s)) >= 0) {
			result.append(str.substring(s, e));
			result.append(replace);
			s = e + pattern.length();
		}
		result.append(str.substring(s));
		return result.toString();
	}

	/**
	 * ��һ���ַ�ָ�ɶ���
	 * 
	 * @param src
	 * @param lineLength
	 *            length of a line
	 * @return �ָ����ַ�
	 */
	public static String split2MultiLine(String src, int lineLength) {
		int srcLength = src.length();
		if (srcLength <= lineLength) {
			return src;
		}
		StringBuffer sb = new StringBuffer();
		int loopCnt = 0;
		int i = 1;

		for (;;) {
			if (i * lineLength > srcLength) {
				sb.append(src.substring(loopCnt));
				break;
			} else {
				sb.append(src.substring(loopCnt, i * lineLength));
			}
			sb.append("��");
			// loopCnt = i * lineLength - 1;
			loopCnt = i * lineLength;
			i++;
		}
		return sb.toString();
	}

	/**
	 * �Ѵ�����TableField���ת�ɲ�������TableField���
	 * 
	 * @param tableField
	 * @return �ֶ���
	 */
	public static String truncTableField(String tableField) {
		return tableField.substring(tableField.indexOf('.') + 1, tableField
				.length());
	}

	/**
	 * GBK����ת��
	 * 
	 * @param src
	 *            ��Ҫת�����ִ�
	 * @return ת����GBK�������ִ�
	 */
	public static String getGBKString(String src) {
		try {
			return System.getProperty("user.language").equalsIgnoreCase("zh") ? src
					: new String(src.getBytes("ISO-8859-1"), "GBK");
		} catch (UnsupportedEncodingException e) {
			return src;
		}

	}

	/**
	 * ISO8859����ת��
	 * 
	 * @param src
	 *            ��Ҫת�����ִ�
	 * @return ת����GBK�������ִ�
	 */
	public static String getISO8859String(String src) {
		try {
			return System.getProperty("user.language").equalsIgnoreCase("zh") ? src
					: new String(src.getBytes("GBK"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			return src;
		}

	}

	/**
	 * ����URL�Ĵ�SessionId�ı���
	 * 
	 * @param url
	 *            URL�ַ�
	 * @param request
	 * @return String
	 */
	public static String toEncoded(String url, HttpServletRequest request) {

		String sessionId = request.getSession().getId();
		/** @todo��Ҫ�޸� */

		if ((url == null) || (sessionId == null)) {
			return (url);
		}
		// �����ĸ��ַ��ǰ׺
		sessionId = "0000" + sessionId;

		String path = url;
		String query = "";
		String anchor = "";
		int question = url.indexOf('?');
		if (question >= 0) {
			path = url.substring(0, question);
			query = url.substring(question);
		}
		int pound = path.indexOf('#');
		if (pound >= 0) {
			anchor = path.substring(pound);
			path = path.substring(0, pound);
		}
		StringBuffer sb = new StringBuffer(path);
		if (sb.length() > 0) { // jsessionid can't be first.
			sb.append(";jsessionid=");
			sb.append(sessionId);
		}
		sb.append(anchor);
		sb.append(query);
		return (sb.toString());

	}

	/**
	 * ���鸽����
	 * 
	 * @param request
	 * @param sStr
	 *            Դ������
	 * @param tStr
	 *            Ŀ�긽���루�������
	 * @return String
	 */
	public static boolean checkVerifyCode(HttpServletRequest request,
			String sStr, String tStr) {
		String tmp = getVerifyCode(request, sStr);
		if (tmp.equals(tStr)) {
			return true;
		}
		return false;
	}

	/**
	 * ��ɼ��ܵĸ�����
	 * 
	 * @param request
	 * @param sStr
	 *            Դ������
	 * @return String
	 */
	public static String getVerifyCode(HttpServletRequest request, String sStr) {
		String tmp = "";
		HttpSession session = request.getSession(true);

		// ��ϲ���Ψһ��һ���ִ�
		if (session != null) {
			tmp = session.getId();
			tmp += sStr;
			tmp += session.getCreationTime();
		} else {
			tmp = sStr;
		}
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(tmp.getBytes());
			BigInteger hash = new BigInteger(1, md.digest());
			tmp = hash.toString(16).toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tmp;

	}

	/**
	 * �����ļ�
	 * 
	 * @param src
	 *            Դ�ļ�·��
	 * @param des
	 *            Ŀ���ļ�·��
	 */
	public static boolean copyFile(String src, String des) {
		boolean ret = false;
		// ���Դ�ļ��Ƿ����
		File file = new File(src);
		if (!file.isFile()) {
			log.debug("copyFile error: the src file don't exist");
			return ret;
		}
		// ����Ŀ��Ŀ¼
		// int dirLen = des.lastIndexOf(File.separator);
		des = des.replace(File.separator.charAt(0), '/');
		int dirLen = des.lastIndexOf("/");
		String desDir = des.substring(0, dirLen);
		file = new File(desDir);
		if (!file.exists()) {
			file.mkdirs();
		}
		// �����ļ�
		try {
			FileInputStream fis = new FileInputStream(src);
			FileOutputStream fos = new FileOutputStream(des);
			/*
			 * int c; while ((c = fis.read()) != -1){ fos.write(c); }
			 */
			File f = new File(src);
			byte buf[] = new byte[(int) f.length()];
			if (fis.read(buf) != -1) {
				fos.write(buf);
			}
			fos.close();
			fis.close();
			ret = true;
		} catch (Exception e) {
			log.error("copyFile error:" + e, e);
		}
		return ret;

	}

	/**
	 * ����Ŀ¼
	 * 
	 * @param src
	 *            ԴĿ¼
	 * @param des
	 *            Ŀ��Ŀ¼
	 */
	public static boolean copyDir(String src, String des) {
		boolean ret = false;
		// ���ԴĿ¼�Ƿ����
		File file = new File(src);
		if (!file.isDirectory()) {
			return ret;
		}
		// ����Ŀ��Ŀ¼
		file = new File(des);
		if (!file.exists()) {
			file.mkdirs();
		}
		File[] files = (new File(src)).listFiles();
		for (int i = 0; i < files.length; i++) {
			if (files[i].isFile()) {
				copyFile(src + "/" + files[i].getName(), des + "/"
						+ files[i].getName());
			}
		}
		ret = true;
		return ret;
	}

	/**
	 * �ƶ��ļ�
	 * 
	 * @param src
	 *            Դ�ļ�·��
	 * @param des
	 *            Ŀ¼�ļ�·��
	 */
	public static boolean moveFile(String src, String des) {
		boolean ret = false;
		if (copyFile(src, des)) {
			try {
				File file = new File(src);
				file.delete();
				ret = true;
			} catch (Exception e) {
				log.error("moveFile error: delete fail," + e, e);
			}
		}
		return ret;
	}

	/**
	 * ɾ���ļ�
	 * 
	 * @param src
	 *            Դ�ļ�·��
	 */
	public static boolean deleteFile(String src) {
		boolean ret = false;
		try {
			File file = new File(src);
			file.delete();
			ret = true;
		} catch (Exception e) {
			log.error("deleteFile error: " + e, e);
		}
		return ret;
	}

	/**
	 * ����ʵ��ǿ�����ֵ(ֻ�ܶ�ͬһ����Ķ�����п���)
	 * 
	 * @param des
	 *            Ŀ��ʵ��
	 * @param src
	 *            Դʵ��
	 */
	public static void copyNotNullProperties(Object des, Object src) {

		PropertyDescriptor[] pros = PropertyUtils.getPropertyDescriptors(des);
		for (int i = 0; i < pros.length; i++) {
			String prosName = pros[i].getName();
			if (PropertyUtils.isWriteable(des, prosName)) {
				try {
					Object val = PropertyUtils.getProperty(src, prosName);
					if (null != val) {
						PropertyUtils.setProperty(des, prosName, val);
					}
				} catch (Exception e) {
					log.error("copyNotNullProperties error:" + e, e);
				}
			}

		}
	}

	/**
	 * �ϴ��ļ�
	 * 
	 * @param file
	 *            �ļ��?
	 * @param path
	 *            Ŀ¼·��
	 */
	public static void uploadFile(FormFile file, String path) {
		try {
			OutputStream bos = new FileOutputStream(path);
			InputStream stream = file.getInputStream();
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
				bos.write(buffer, 0, bytesRead);
			}
			bos.close();
			stream.close();
		} catch (Exception e) {
			log.error("exception:" + e, e);
		}
	}

	/**
	 * ��requestȡ�÷�ҳ��¼��
	 * 
	 * @param request
	 * @param defaultRows
	 *            ȱʡ��¼��
	 * @return ÿҳ��¼��
	 */
	public static int getPageRows(HttpServletRequest request, int defaultRows) {
		String pageRows = request.getParameter("pageRows");
		if (null == pageRows || pageRows.equals("")) {
			pageRows = (String) request.getSession().getAttribute("pageRows");
			if (null == pageRows || pageRows.equals("")) {
				pageRows = String.valueOf(defaultRows);
			}
		}
		request.getSession().setAttribute("pageRows", pageRows);
		int ret = defaultRows;
		try {
			ret = Integer.parseInt(pageRows);
		} catch (Exception e) {
			log.error("Util.getPageRows() parseInt(" + pageRows + ")");
		}
		return ret;
	}

	// ����Ŀ��Ҫ���ܸ��ĳЩ��ѯ�������������������ĸ��Ϊ�������в�ѯ�������һ���С�������ˣ��������롮zs'��
	// д��һ�����������£�
	/**
	 * GB 2312-80 ����¼�ĺ��ֳַ���������һ�������ǳ��ú��֣��� 3755 ���� ���� 16��55
	 * ������ƴ����ĸ������˳�����У��ڶ��������Ǵγ��ú��֣� �� 3008 �������� 56��87 �����ף��ʻ�˳�����У����Ա�����ֻ�ܲ鵽
	 * ��һ�����ֵ���ĸ��ͬʱ�Է����ĸ��zh��ch��sh��ֻ��ȡ����ĸ��z��c��s��
	 */

	// ��������λ��ת������
	static final int GB_SP_DIFF = 160;

	// ��Ź��һ�����ֲ�ͬ��������ʼ��λ��
	static final int[] secPosvalueList = { 1601, 1637, 1833, 2078, 2274, 2302,
			2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027,
			4086, 4390, 4558, 4684, 4925, 5249, 5600 };

	// ��Ź��һ�����ֲ�ͬ��������ʼ��λ���Ӧ����
	static final char[] firstLetter = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
			'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x',
			'y', 'z' };

	/**
	 * ��ȡһ�������ַ��ƴ������ĸ
	 * 
	 * @param srcStr
	 *            Դ�ַ�
	 * @return ����ĸ
	 */
	public static String getGBKInitial(String srcStr) {
		srcStr = srcStr.toLowerCase();
		StringBuffer buffer = new StringBuffer();
		char ch;
		char[] temp;
		try {
			for (int i = 0; i < srcStr.length(); i++) { // ���δ���str��ÿ���ַ�
				ch = srcStr.charAt(i);
				temp = new char[] { ch };
				byte[] uniCode = new String(temp).getBytes("GBK");
				if (uniCode[0] < 128 && uniCode[0] > 0) { // �Ǻ���
					buffer.append(temp);
				} else {
					buffer.append(convert(uniCode));
				}
			}
		} catch (Exception e) {
			log.error("getGBKInitial " + srcStr + " error:" + e);
		}
		return buffer.toString();
	}

	/**
	 * ��ȡһ�����ֵ�ƴ������ĸ�� GB�������ֽڷֱ��ȥ160��ת����10��������ϾͿ��Եõ���λ��
	 * ���纺�֡��㡱��GB����0xC4/0xE3���ֱ��ȥ0xA0��160������0x24/0x43
	 * 0x24ת��10���ƾ���36��0x43��67����ô�����λ�����3667���ڶ��ձ��ж���Ϊ��n��
	 * 
	 * @param bytes
	 * @return ת���������ĸ
	 */
	private static char convert(byte[] bytes) {

		char result = '-';
		int secPosvalue = 0;
		int i;
		for (i = 0; i < bytes.length; i++) {
			bytes[i] -= GB_SP_DIFF;
		}
		secPosvalue = bytes[0] * 100 + bytes[1];
		for (i = 0; i < 23; i++) {
			if (secPosvalue >= secPosvalueList[i]
					&& secPosvalue < secPosvalueList[i + 1]) {
				result = firstLetter[i];
				break;
			}
		}
		return result;
	}

	/**
	 * �������ַ�����ļ�
	 * 
	 * @param srcUrl
	 *            Դ��ַ
	 * @param desPath
	 *            Ŀ¼·��
	 */
	public static void copyURLFile(String srcUrl, String desPath) {
		HttpClient client = null;
		HttpMethod method = null;
		try {
			client = new HttpClient();
			method = new GetMethod(srcUrl);

			int statusCode = client.executeMethod(method);
			if (statusCode != -1) {
				desPath = desPath.replace(File.separator.charAt(0), '/');
				int dirLen = desPath.lastIndexOf("/");
				String desDir = desPath.substring(0, dirLen);
				File file = new File(desDir);
				if (!file.exists()) {
					file.mkdirs();
				}
				InputStream is = method.getResponseBodyAsStream();
				BufferedInputStream bis = new BufferedInputStream(is);
				FileOutputStream fos = new FileOutputStream(desPath);
				int bytesRead = 0;
				byte[] buffer = new byte[8192];
				while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
					fos.write(buffer, 0, bytesRead);
				}
				fos.close();
				bis.close();
				is.close();
			}

		} catch (Exception e) {
			log.error("copyURLFile error:" + e, e);
		} finally {
			method.releaseConnection();
			method = null;
			client = null;
		}

	}

	/**
	 * ѹ���ļ�
	 * 
	 * @param inputFileName
	 *            Դ�ļ�
	 * @param outputFileName
	 *            Ŀ���ļ�
	 */
	public static void zipFile(String inputFileName, String outputFileName) {
		try {
			// ��֤Ŀ���ļ�����Ŀ¼����
			outputFileName = outputFileName.replace(File.separator.charAt(0),
					'/');
			int dirLen = outputFileName.lastIndexOf("/");
			String desDir = outputFileName.substring(0, dirLen);
			File f = new File(desDir);
			if (!f.exists()) {
				f.mkdirs();
			}
			// �����ļ�
			File file = new File(inputFileName);
			// �����ļ���
			FileInputStream in = new FileInputStream(file);
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
					outputFileName));
			out.putNextEntry(new ZipEntry(file.getName()));
			// д���ļ�
			/*
			 * int b; while ((b = in.read()) != -1) { out.write(b); }
			 */
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {
				out.write(buffer, 0, bytesRead);
			}
			in.close();
			out.close();
		} catch (Exception e) {
			log.error("zipFile error:" + e, e);
		}
	}

	/**
	 * ��ѹ���ļ�
	 * 
	 * @param zipFileName
	 *            Դ�ļ�
	 * @param outputFileName
	 *            Ŀ���ļ�
	 */
	public static void unzipFile(String zipFileName, String outputFileName) {
		try {
			ZipInputStream in = new ZipInputStream(new FileInputStream(
					zipFileName));
			ZipEntry z = null;
			while ((z = in.getNextEntry()) != null) {
				if (false == z.isDirectory()) {
					outputFileName = outputFileName.replace(File.separator
							.charAt(0), '/');
					int dirLen = outputFileName.lastIndexOf("/");
					String desDir = outputFileName.substring(0, dirLen);
					File file = new File(desDir);
					if (!file.exists()) {
						file.mkdirs();
					}
					FileOutputStream out = new FileOutputStream(outputFileName);
					/*
					 * int b; while ((b = in.read()) != -1) out.write(b);
					 */
					int bytesRead = 0;
					byte[] buffer = new byte[8192];
					while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {
						out.write(buffer, 0, bytesRead);
					}
					out.close();
					break;// ֻ��ѹһ���ļ�
				}
			}
			in.close();
		} catch (Exception e) {
			log.error("unzipFile error:" + e, e);
		}
	}

}
